package com.niiwoo.civet.account.service.local.refund.newRefund;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.constant.RedissonLockConstant;
import com.niiwoo.civet.account.dao.entity.AccountBase;
import com.niiwoo.civet.account.dao.entity.BankCard;
import com.niiwoo.civet.account.dao.entity.PayChannel;
import com.niiwoo.civet.account.dao.entity.RefundDataException;
import com.niiwoo.civet.account.dao.mapper.AccountBaseMapperExt;
import com.niiwoo.civet.account.dao.mapper.BankCardMapperExt;
import com.niiwoo.civet.account.dao.mapper.PayChannelMapperExt;
import com.niiwoo.civet.account.dao.mapper.RefundDataExceptionMapper;
import com.niiwoo.civet.account.dto.common.AccountBatchTransOrderDTO;
import com.niiwoo.civet.account.enums.OrderEndTypeEnum;
import com.niiwoo.civet.account.enums.RefundStatusEnum;
import com.niiwoo.civet.account.service.AccountRefundOrderPushDubboService;
import com.niiwoo.civet.base.enums.RefundBizStatusEnum;
import com.niiwoo.civet.trade.dto.common.BatchTransOrderDetailForAccountDTO;
import com.niiwoo.civet.trade.dto.common.TradeBatchTransOrderDTO;
import com.niiwoo.civet.trade.enums.BatchRefundTypeEnum;
import com.niiwoo.civet.trade.service.refund.RepaymentDubboService;
import com.niiwoo.tripod.lanmao.component.LanMaoDirectService;
import com.niiwoo.tripod.lanmao.component.LanMaoSequence;
import com.niiwoo.tripod.lanmao.enums.*;
import com.niiwoo.tripod.lanmao.properties.LanMaoProperties;
import com.niiwoo.tripod.lanmao.response.AsyncTransactionResponse;
import com.niiwoo.tripod.lanmao.response.DirectRechargeResponse;
import com.niiwoo.tripod.lanmao.response.LanMaoResponse;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import reactor.core.support.Assert;

import java.math.BigDecimal;
import java.util.concurrent.ExecutionException;

/**
 * Created by dell on 2018/1/31.
 *  公共还款子流程服务
 */
@Service
@Slf4j
public class AccountRefundHandleLocalService {

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private AccountBaseMapperExt accountBaseMapperExt;
    @Autowired
    private LanMaoSequence lanMaoSequence;
    @Autowired
    private RefundBaseLocalService refundBaseLocalService;
    @Autowired
    private LanMaoDirectService lanMaoDirectService;
    @Autowired
    private RefundDataExceptionMapper refundDataExceptionMapper;
    @Reference(version = "1.0.0")
    private RepaymentDubboService repaymentDubboService;
    @Reference(version = "1.0.0")
    private AccountRefundOrderPushDubboService accountRefundOrderPushDubboService;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Reference(version = "1.0.0")
    private com.niiwoo.civet.user.service.UserLoginAccountDubboService userLoginAccountDubboService;
    @Autowired
    private RefundQueryLocalService refundQueryLocalService;
    @Autowired
    private BankCardMapperExt bankCardMapperExt;
    @Autowired
    private PayChannelMapperExt payChannelMapperExt;
    @Autowired
    private RefundMsgLocalService refundMsgLocalService;
    @Autowired
    private LanmaoRefundLocalService lanmaoRefundLocalService;
    @Autowired
    private LanMaoProperties lanMaoProperties;





    /**
     * 余额不足还款流程(余额不足，自动代扣)
     * 异步
     */
    public void amountNotEnough(AccountBatchTransOrderDTO dto, AccountBase account, Long refundOrderId) throws ExecutionException, InterruptedException {

        Assert.isTrue(dto.getAmount().compareTo(account.getAvailableAmount())>=0,"逾期充足，不可代扣");
        //计算不足金额(代扣金额)
        BigDecimal notEnoughAmount = dto.getAmount().subtract(account.getAvailableAmount());

        Long withHoldOrderId = snowflakeIdWorker.nextId();
        DirectRechargeResponse resp = withholdToLanmao(dto,account,notEnoughAmount,withHoldOrderId);

        if (resp == null){
            log.info("代扣请求发送成功，等待异步结果");
            return;
        }

        //todo 业务处理失败且不为系统异常
        if (RechargeStatusEnum.FAIL.name().equals(resp.getRechargeStatus())) {
            log.error("代扣失败,代扣订单{},原因{}", withHoldOrderId, resp.getErrorMessage());
            //发送消息
            log.info("amountNotEnough.cardWithholdFailMsgSend 代扣失败 start");
            refundMsgLocalService.cardWithholdFailMsgSend(dto);
            log.info("amountNotEnough.cardWithholdFailMsgSend 代扣失败 end");
            this.withholdFail(withHoldOrderId, refundOrderId, dto.getProjectId(), dto.getCurrentPeriod(), dto.getBatchRequestNo());
            return;
        }
        //支付中
        else if (RechargeStatusEnum.PENDDING.name().equals(resp.getRechargeStatus())) {
            log.warn("订单支付中,代扣订单号{}", withHoldOrderId);
            return;
        }
        //支付成功
        else if (ResponseCodeEnum.SUCCESS.getValue().equals(resp.getCode())
                && ResponseStatusEnum.SUCCESS.name().equals(resp.getStatus())
                && RechargeStatusEnum.SUCCESS.name().equals(resp.getRechargeStatus())) {
            //更新账户余额和代扣订单状态
            int count = refundBaseLocalService.updateWithHoldOrderStatusAndAccountAmount(account.getId(), withHoldOrderId, notEnoughAmount, OrderEndTypeEnum.AUTO, dto);
            if (count == 1) {
                //余额充足流程
                this.amountEnough(dto, account.getId(), account.getAccountNo(), refundOrderId);
            }
        }
    }


    /**
     * 同步处理 金额不足流程
     * @param dto
     * @param account
     * @param refundOrderId
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public RefundBizStatusEnum amountNotEnoughSync(AccountBatchTransOrderDTO dto, AccountBase account, Long refundOrderId) throws ExecutionException, InterruptedException {
        //计算不足金额(代扣金额)
        BigDecimal notEnoughAmount;
        if (dto.getWithholdAmount().compareTo(BigDecimal.ZERO) > 0) {
            notEnoughAmount = dto.getWithholdAmount();
        } else {
            notEnoughAmount = dto.getAmount().subtract(account.getAvailableAmount());
        }

        Long withHoldOrderId = snowflakeIdWorker.nextId();
        DirectRechargeResponse resp = this.withholdToLanmao(dto,account,notEnoughAmount,withHoldOrderId);
        if (resp == null){
            log.info("代扣请求发送成功，等待异步结果");
            return RefundBizStatusEnum.WITHHOLD_INIT;
        }
        if (RechargeStatusEnum.FAIL.name().equals(resp.getRechargeStatus())) {
            log.error("代扣失败,代扣订单{},原因{}", withHoldOrderId, resp.getErrorMessage());
            //发送消息
            log.info("amountNotEnoughForManage.cardWithholdFailMsgSend 代扣失败 start");
            refundMsgLocalService.cardWithholdFailMsgSend(dto);
            log.info("amountNotEnoughForManage.cardWithholdFailMsgSend 代扣失败 end");
            this.withholdFail(withHoldOrderId, refundOrderId, dto.getProjectId(), dto.getCurrentPeriod(), dto.getBatchRequestNo());
            return RefundBizStatusEnum.WITHHOLD_FAIL;
        }
        //支付中
        else if (RechargeStatusEnum.PENDDING.name().equals(resp.getRechargeStatus())) {
            log.warn("订单支付中,代扣订单号{}", withHoldOrderId);
            return RefundBizStatusEnum.WITHHOLD_INIT;
        }
        //支付成功
        else if (ResponseCodeEnum.SUCCESS.getValue().equals(resp.getCode())
                && ResponseStatusEnum.SUCCESS.name().equals(resp.getStatus())
                && RechargeStatusEnum.SUCCESS.name().equals(resp.getRechargeStatus())) {
            //更新账户余额和代扣订单状态
            int count = refundBaseLocalService.updateWithHoldOrderStatusAndAccountAmount(account.getId(), withHoldOrderId, notEnoughAmount, OrderEndTypeEnum.AUTO, dto);
            if (count == 1) {
                //余额充足流程
                return this.amountEnoughSync(dto, account.getId(), account.getAccountNo(), refundOrderId);
            }
        }
        return null;

    }


    /**
     *
     * @param dto
     * @param account
     * @param withHoldOrderId
     * @param amount  代扣金额
     * @return
     */
    private PayChannel insertWithHoldOrder(AccountBatchTransOrderDTO dto,AccountBase account,Long withHoldOrderId,BigDecimal amount){
        //根据用户ID查询银行卡信息
        BankCard card = bankCardMapperExt.selectSimpleUserBankCard(dto.getBorrowerUserId());
        if (card == null) {
            throw new BizException("ACC10005", "借款人银行卡信息不存在");
        }
        //查询支付渠道信息
        PayChannel payChannel = payChannelMapperExt.selectWithHoldChannelByBank(card.getBankTypeId());
        if (payChannel == null) {
            //发送消息
            log.info("amountNotEnoughForManage.accountWithholdFailMsgSend start");
            refundMsgLocalService.accountWithholdFailMsgSend(dto);
            log.info("amountNotEnoughForManage.accountWithholdFailMsgSend end");
            throw new BizException("ACC10006", "支付渠道不存在");
        }
        refundBaseLocalService.insertWithHoldOrder(dto, account, card, payChannel, withHoldOrderId,amount);

        return payChannel;
    }

    /**
     *
     * @param dto
     * @param account
     * @param amount 代扣金额
     * @param withHoldOrderId
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public DirectRechargeResponse  withholdToLanmao(AccountBatchTransOrderDTO dto,AccountBase account,BigDecimal amount,Long withHoldOrderId) throws ExecutionException, InterruptedException {

        //调用存管接口进行代扣
        String withholdRequestNo = lanMaoSequence.getRequestNo();
        //String proxyPretransRequestNo = lanMaoSequence.getRequestNo();
        dto.setWithholdRequestNo(withholdRequestNo);
        //dto.setFreezeRequestNo(proxyPretransRequestNo);
        PayChannel payChannel =  this.insertWithHoldOrder(dto,account,withHoldOrderId,amount);

        //插入代扣订单
        DirectRechargeResponse resp = lanmaoRefundLocalService.directRecharge(account.getAccountNo(), withholdRequestNo, amount, PayCompanyEnum.enumOf(payChannel.getChannelCode().toUpperCase()));
        if (resp == null) {
            log.info("存管系统自动充值请求已发送,withholdRequestNo={}",withholdRequestNo);
            //发送消息
            /*log.info("amountNotEnough.cardWithholdFailMsgSend 存管无响应 start");
            refundMsgLocalService.cardWithholdFailMsgSend(dto);
            log.info("amountNotEnough.cardWithholdFailMsgSend 存管无响应 end");*/
        }

        return resp;
    }

    /**
     * 代扣还款
     * @param dto
     * @param account
     * @param refundOrderId
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public RefundBizStatusEnum withholdRefundWithFreeze(AccountBatchTransOrderDTO dto,AccountBase account, Long refundOrderId) throws ExecutionException, InterruptedException {
        log.info("withholdRefund(),start---projectId={}", dto.getProjectId());
        Assert.isTrue(dto.getIsWithHoldRefund(),"参数错误");

        String proxyPretransRequestNo = lanMaoSequence.getRequestNo();
        String proxyAppendRequestNo = lanMaoSequence.getRequestNo();
        String withholdRequestNo = lanMaoSequence.getRequestNo();
        dto.setFreezeRequestNo(proxyAppendRequestNo);
        dto.setProxyPretransRequestNo(proxyPretransRequestNo);
        dto.setWithholdRequestNo(withholdRequestNo);
        Long withholdOrderId = snowflakeIdWorker.nextId();

        //按指定金额扣款
        PayChannel payChannel = this.insertWithHoldOrder(dto,account,withholdOrderId,dto.getAmount());
        //生成代扣预处理订单

        DirectRechargeResponse resp = lanmaoRefundLocalService.directRechargeWithFreeze(account.getAccountNo(),withholdRequestNo,proxyPretransRequestNo,proxyAppendRequestNo,dto.getAmount(),PayCompanyEnum.enumOf(payChannel.getChannelCode().toUpperCase()));
        if (resp == null) {
            log.error("存管系统自动充值请求无响应");
            //发送消息
            log.info("amountNotEnough.cardWithholdFailMsgSend 存管无响应 start");
            refundMsgLocalService.cardWithholdFailMsgSend(dto);
            log.info("amountNotEnough.cardWithholdFailMsgSend 存管无响应 end");
        }
        if (ResponseCodeEnum.FAILURE.getValue().equals(resp.getCode())
                || (ResponseStatusEnum.INIT.getValue().equals(resp.getStatus()) && !"100001".equals(resp.getErrorCode()))) {
            //修改预处理订单为失败,中止流程
            refundBaseLocalService.withHoldFailRollBackStatus(dto.getBatchRequestNo(), refundOrderId, dto.getBatchTransOrderId());
            return RefundBizStatusEnum.WITHHOLD_FAIL;
        }
        //支付中
        else if (RechargeStatusEnum.PENDDING.name().equals(resp.getRechargeStatus())) {
            log.warn("订单支付中,代扣订单号{}", withholdOrderId);
            return RefundBizStatusEnum.WITHHOLD_INIT;
        }
        //支付成功
        else if (ResponseCodeEnum.SUCCESS.getValue().equals(resp.getCode())
                && ResponseStatusEnum.SUCCESS.name().equals(resp.getStatus())
                && RechargeStatusEnum.SUCCESS.name().equals(resp.getRechargeStatus())) {
            Long proOrderId = refundBaseLocalService.preProcessRepayment(dto,account.getId(),proxyAppendRequestNo);
            dto.setProTransOrderId(proOrderId);
            //预处理成功
            int count = refundBaseLocalService.updateWithHoldOrderStatusAndAccountAmount(account.getId(), withholdOrderId, dto.getAmount(), OrderEndTypeEnum.AUTO, dto);

            if ("SUCCESS".equals(resp.getProxyPretransStatus())){
                refundBaseLocalService.updateProTransactionOrderStatusAndAccountAmount(proOrderId,account.getId(),dto.getAmount(),dto);
                if (count == 1) {
                    //代扣成功流程
                    //调用交易中心配帐接口
                    BatchTransOrderDetailForAccountDTO batchTransOrderDetailForAccountDTO = this.callTradeCenterGenerateBizs(dto);

                    //插入订单明细
                    try {
                        refundBaseLocalService.insertOrderDetailsAndSaveBills(batchTransOrderDetailForAccountDTO, dto);
                    } catch (Exception e) {
                        log.error("配账失败:", e);
                        return RefundBizStatusEnum.REFUND_FAIL;
                    }

                    //调用存管批量交易接口
                    AsyncTransactionResponse asyncTransactionResponse = lanmaoRefundLocalService.asyncTransaction(batchTransOrderDetailForAccountDTO, dto.getBatchRequestNo());
                    if (asyncTransactionResponse == null) {
                        log.error("存管系统批量交易请求无响应");
                        return RefundBizStatusEnum.REFUND_INIT;
                    }
                    if (ResponseStatusEnum.INIT.getValue().equals(asyncTransactionResponse.getStatus())) {
                        log.error("存管还款接口调用响应失败，请查看具体原因projectId={}", dto.getProjectId());
                        return RefundBizStatusEnum.REFUND_FAIL;
                    }
                    return RefundBizStatusEnum.REFUND_INIT;
                }
            }else {
                log.info("充值成功，但是代扣预处理没有成功，请检查！！,withholdOrderId={}",withholdOrderId);
            }

        }
        return null;

    }

    /**
     * 还款预处理+还款
     * 余额充足还款流程
     * app调用
     */
    public RefundBizStatusEnum amountEnoughSync(AccountBatchTransOrderDTO dto, Long accountId, String accountNo, Long refundOrderId) throws BizException, ExecutionException, InterruptedException {

        log.info("amountEnoughForApp(),start---projectId={}", dto.getProjectId());
        String freezePreTransactionRequestNo = lanMaoSequence.getRequestNo();
        //生成还款预处理订单
        Long orderId = refundBaseLocalService.preProcessRepayment(dto, accountId, freezePreTransactionRequestNo);
        //调用存管授权预处理接口
        dto.setFreezeRequestNo(freezePreTransactionRequestNo);
        dto.setProTransOrderId(orderId);
        Assert.isTrue(!dto.getIsWithHoldRefund(),"代扣还款不可进行还款预处理");
        LanMaoResponse resp = lanmaoRefundLocalService.userAutoPreTransaction(freezePreTransactionRequestNo, accountNo, dto.getAmount(), dto.getProjectId());

        //如果冻结预处理请求失败
        if (resp == null || "100001".equals(resp.getErrorCode())) {
            log.error("存管系统冻结预处理请求无响或内部异常");
            return RefundBizStatusEnum.PRO_TRANSACTION_INIT;
        }
        if (ResponseCodeEnum.FAILURE.getValue().equals(resp.getCode())
                || (ResponseStatusEnum.INIT.getValue().equals(resp.getStatus()) && !"100001".equals(resp.getErrorCode()))) {
            //修改预处理订单为失败,中止流程
            log.info("修改预处理订单为失败,中止流程,预处理请求号{}",freezePreTransactionRequestNo);
            refundBaseLocalService.freezePreTransactionFailRollBackStatus(orderId, refundOrderId, dto.getBatchRequestNo());
            return RefundBizStatusEnum.PRO_TRANSACTION_FAIL;
        }
        //更新账户额度,修改预处理订单状态为成功
        if (!resp.isSuccess()){
            log.info("预处理冻结失败，预处理请求号:{}",freezePreTransactionRequestNo);
            return RefundBizStatusEnum.PRO_TRANSACTION_FAIL;
        }
        refundBaseLocalService.updateProTransactionOrderStatusAndAccountAmount(orderId, accountId, dto.getAmount(), dto);
        //调用交易中心配帐接口
        BatchTransOrderDetailForAccountDTO batchTransOrderDetailForAccountDTO = this.callTradeCenterGenerateBizs(dto);
        //插入订单明细
        try {
            refundBaseLocalService.insertOrderDetailsAndSaveBills(batchTransOrderDetailForAccountDTO, dto);
        } catch (Exception e) {
            log.error("批次号{}配账失败:",dto.getBatchRequestNo(), e);
            return RefundBizStatusEnum.REFUND_FAIL;
        }

        //调用存管批量交易接口
        AsyncTransactionResponse asyncTransactionResponse = lanmaoRefundLocalService.asyncTransaction(batchTransOrderDetailForAccountDTO, dto.getBatchRequestNo());
        if (asyncTransactionResponse == null) {
            log.error("存管系统批量交易请求无响应");
            return RefundBizStatusEnum.REFUND_INIT;
        }
        if (ResponseStatusEnum.INIT.getValue().equals(asyncTransactionResponse.getStatus())) {
            log.error("存管还款接口调用响应失败，请查看具体原因projectId={},resp={}", dto.getProjectId(), JSON.toJSONString(asyncTransactionResponse));
            return RefundBizStatusEnum.REFUND_FAIL;
        }
        return RefundBizStatusEnum.REFUND_INIT;
    }



    /**
     * 余额还款流程
     */
    public void amountEnough(AccountBatchTransOrderDTO dto, Long accountId, String accountNo, Long refundOrderId) {
//        RLock lock = redissonClient.getLock(new StringBuffer().append(RedissonLockConstant.REFUND_TRADE_TYPE).append(TransactionTypeEnum.REPAYMENT.name()).append(RedissonLockConstant.REFUND_ACCOUNT).append(dto.getBorrowerUserId()).toString());
//        try {
//            lock.lock();
//            String freezePreTransactionRequestNo = lanMaoSequence.getRequestNo();
//            Long orderId = null;
//            LanMaoResponse resp = null;
//            if (dto.getAmount().compareTo(BigDecimal.ZERO) > 0) {
//                //00:15自动还款，有多少还多少
//                AccountBase accountBase = refundQueryLocalService.getAccountBase(dto);
//                if (accountBase.getAvailableAmount().compareTo(BigDecimal.ZERO) == 0) {
//                    log.info("还款人金额不足，还款金额为dto.amount={}元,user_id={}", dto.getAmount(), accountBase.getUserId());
//                    dto.setAmount(BigDecimal.ZERO);//小于0元借款人不还钱
//                    refundBaseLocalService.updateBatchTransOrderStatus(dto.getBatchRequestNo(), dto.getBatchTransOrderId(), RefundStatusEnum.FAIL);
//                    this.callTradeCenterGenerateBizs(dto);
//                    return;
//                }else {
//                    if (BatchRefundTypeEnum.NEED_GUARANTEE_REFUND.getValue().equals(dto.getBatchRefundType())) {
//                        //00:15自动还款
//                        BigDecimal forFrozenAmount = dto.getAmount().compareTo(accountBase.getAvailableAmount()) >= 0 ? accountBase.getAvailableAmount() : dto.getAmount();
//                        dto.setAmount(forFrozenAmount);
//                    }
//                    // 9：00  16：00  21:00 应还多少即还多少(逾期标的，应还金额传入时已经更新)
//                    orderId = refundBaseLocalService.preProcessRepayment(dto, accountId, freezePreTransactionRequestNo);
//
//                    //调用存管授权预处理接口
//                    dto.setFreezeRequestNo(freezePreTransactionRequestNo);
//                    dto.setProTransOrderId(orderId);
//                    if (dto.getTradeType().equals(TransactionTypeEnum.REPAYMENT.getValue())) {
//                        resp = lanmaoRefundLocalService.userAutoPreTransaction(freezePreTransactionRequestNo, accountNo, dto.getAmount(), dto.getProjectId());
//                    } else if (dto.getTradeType().equals(TransactionTypeEnum.COMPENSATORY.getValue())) {
//                        resp = lanmaoRefundLocalService.userAutoPreTransactionForGuarantee(freezePreTransactionRequestNo, accountNo, dto.getAmount(), dto.getProjectId());
//                    }
//                }
//            } else {
//                log.info("待还款金额为0,accountNo={}", accountNo);
//                return;
//            }
//            //如果冻结预处理请求失败
//            if (resp == null || "100001".equals(resp.getErrorCode())) {
//                log.error("存管系统冻结预处理请求无响应 或内部异常");
//                return;
//            }
//            //调用失败  或者处理失败且非系统异常（100001）终止
//            else if (ResponseCodeEnum.FAILURE.getValue().equals(resp.getCode())
//                    || (ResponseStatusEnum.INIT.getValue().equals(resp.getStatus()) && !resp.getErrorCode().equals("100001"))) {
//                //修改预处理订单为失败,中止流程
//                log.info("还款预处理处理失败,requestNo={},code={},errorCode={},erroeMessage={}",freezePreTransactionRequestNo,resp.getCode(),resp.getErrorCode(),resp.getErrorMessage());
//
//                this.proTransactionFail(orderId, refundOrderId, dto.getProjectId(), dto.getCurrentPeriod(), dto.getBatchRequestNo());
//                throw new BizException("ACC10009");
//            }
//
//            //更新账户额度,修改预处理订单状态为成功
//            if (orderId != null) {
//                int count = refundBaseLocalService.updateProTransactionOrderStatusAndAccountAmount(orderId, accountId, dto.getAmount(), dto);
//                if (count == 1) {
//                    //还款逻辑
//                    this.refund(dto, refundOrderId);
//                }
//            }
//        } finally {
//            lock.unlock();
//        }
    }

    /**
     * 还款逻辑
     *
     * @param dto
     * @param refundOrderId
     */
    public void refund(AccountBatchTransOrderDTO dto, Long refundOrderId) {

        //调用交易中心配帐接口
        TradeBatchTransOrderDTO tradeDto = new TradeBatchTransOrderDTO();
        BeanUtils.copyProperties(dto, tradeDto);
        //调用交易中心配帐接口
        BatchTransOrderDetailForAccountDTO batchTransOrderDetailForAccountDTO = this.callTradeCenterGenerateBizs(dto);

        log.debug("batchTransOrderDetailForAccountDTO={}" + JSON.toJSONString(batchTransOrderDetailForAccountDTO));

        if (batchTransOrderDetailForAccountDTO == null || CollectionUtils.isEmpty(batchTransOrderDetailForAccountDTO.getBatchTransOrderDetails())) {
            log.info("配账结果为空，无可配账金额bathcNo={},batchId={}", dto.getBatchRequestNo(), refundOrderId);
            if (BigDecimal.ZERO.equals(dto.getAmount())) {
                refundBaseLocalService.updateBatchTransOrderStatus(dto.getBatchRequestNo(), refundOrderId, RefundStatusEnum.FAIL);
            }
            return;
        }
        //插入订单明细
        refundBaseLocalService.insertOrderDetailsAndSaveBills(batchTransOrderDetailForAccountDTO, dto);
        //调用存管批量交易接口
        AsyncTransactionResponse resp = lanmaoRefundLocalService.asyncTransaction(batchTransOrderDetailForAccountDTO, dto.getBatchRequestNo());
        if (resp == null) {
            log.error("存管系统批量交易请求无响应");
            return;
        }
        //还款失败
        if (ResponseStatusEnum.INIT.getValue().equals(resp.getStatus())) {
            //修改还款订单为失败,中止流程
            log.error("批量交易（还款）接口调用失败，projectId={},errorCode={},errorMessage={}", dto.getProjectId(),resp.getErrorCode(),resp.getErrorMessage());
            throw new BizException("ACC10015");
        }
    }


    /**
     * 授权预处理失败流程
     */
    public void proTransactionFail(Long proTransactionOrderId, Long refundOrderId, Long projectId, Integer period, String batchNo) {
        refundBaseLocalService.freezePreTransactionFailRollBackStatus(proTransactionOrderId, refundOrderId, batchNo);

        //代扣还款结果通知-还款失败(授权预处理导致的还款失败)
        refundMsgLocalService.sendRefundResult(projectId, period, batchNo);
    }


    /**
     * 代扣失败流程
     */
    public void withholdFail(Long withHoldOrderId, Long refundOrderId, Long projectId, Integer period, String batchNo) {
        //代扣失败订单处理
        refundBaseLocalService.withHoldFailRollBackStatus(batchNo, withHoldOrderId, refundOrderId);

        //代扣还款结果通知-代扣失败
        refundMsgLocalService.sendRefundResult(projectId, period, batchNo);
    }



    /**
     * 请求交易中心配账接口
     *
     * @param dto
     * @return
     */
    public BatchTransOrderDetailForAccountDTO callTradeCenterGenerateBizs(AccountBatchTransOrderDTO dto) {
        //调用交易中心配帐接口
        log.info("callTradeCenterGenerateBizs()--,配账接口准备调用");
        TradeBatchTransOrderDTO tradeDto = new TradeBatchTransOrderDTO();
        BeanUtils.copyProperties(dto, tradeDto);
        if (BatchRefundTypeEnum.GUARANTEE.getValue().equals(tradeDto.getBatchRefundType())
            && tradeDto.getGuaranteeUserId()==null){
            tradeDto.setGuaranteeUserId(lanMaoProperties.getNiiWooAccount().getGuaranteeUserId());
        }
        BatchTransOrderDetailForAccountDTO batchTransOrderDetailForAccountDTO = null;

        try {
            if (dto.getIsOverDebt()) {
                //提前结清
                batchTransOrderDetailForAccountDTO = repaymentDubboService.generateDetailForOverDebt(tradeDto);
            } else {
                //部分还款，正常还款，逾期还款，坏账还款 通用配账
                batchTransOrderDetailForAccountDTO = repaymentDubboService.generateDetailForNormal(tradeDto);
            }
            if (batchTransOrderDetailForAccountDTO == null){
                log.info("account配账结果为空，请查看!tradeDto={}",JSON.toJSONString(tradeDto));
            }else {
                log.info("account配账结果明细details.Size={}",batchTransOrderDetailForAccountDTO.getBatchTransOrderDetails());
            }
        } catch (Exception e) {
            log.error("配账出现Exception exception,batchNo={},projectId={}", tradeDto.getBatchRequestNo(), tradeDto.getProjectId());
            log.error("配账出现Exception exception",e);
            RefundDataException refundDataException = new RefundDataException();
            refundDataException.setBatchNo(dto.getBatchRequestNo());
            refundDataException.setId(snowflakeIdWorker.nextId());
            refundDataException.setExceptionType((byte) 1);//
            refundDataException.setProjectId(dto.getProjectId());
            refundDataException.setJsonParams(JSON.toJSONString(tradeDto));
            refundDataExceptionMapper.insertSelective(refundDataException);

            RpcContext.getContext().asyncCall(() -> {
                log.error("分账异常，还款回滚,ProTransOrderId={}",dto.getProTransOrderId());
                if (dto == null || dto.getProTransOrderId()==null) {
                    log.info("款回滚,ProTransOrderId=null");
                }else{
                    accountRefundOrderPushDubboService.rollbackProtransaction(dto.getProTransOrderId());
                }
            });
        }
        return batchTransOrderDetailForAccountDTO;
    }

}
